﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using Dycox;
using Dycox.Data;
using Dycox.Linq;

namespace Dycox.Windows.Forms.Design
{
    class ListItemEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }

        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (provider != null && context != null)
            {
                IWindowsFormsEditorService wfes = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
                if (wfes != null)
                {
                    ICollection<IListItem> coll = null;

                    if (_ui == null)
                    {
                        _ui = new ListItemUI();
                    }

                    if (context != null && context.PropertyDescriptor != null)
                    {
                        ListItemConverter lic = context.PropertyDescriptor.Converter as ListItemConverter;
                        if (lic != null) coll = lic.GetStandardItems(context);

                        QueryProperty qfpd = context.PropertyDescriptor as QueryProperty;
                        if (qfpd != null)
                        {
                            _ui.SelectionMode = qfpd.StandardItemsSupport == StandardItemsSupport.Multiple ? SelectionMode.MultiSimple : SelectionMode.One;
                            _ui.AcceptNull = qfpd.Nullable;
                        }
                    }

                    IListItem[] array;
                    if (coll != null) array = coll.ToArray();
                    else array = new IListItem[0];

                    _ui.Start(value, array, wfes);
                    wfes.DropDownControl(_ui);
                    value = _ui.Value;
                }
            }

            return value;
        }

        ListItemUI _ui;

        //[TypeConverter(typeof(NothingListItemConverter))]
        class NothingListItem : IListItem
        {
            public NothingListItem()
            {

            }

            public string Text
            {
                get { return "(无)"; }
            }

            public object Value
            {
                get { return null; }
            }
        }

        //class NothingListItemConverter : TypeConverter
        //{
        //    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        //    {
        //        return true;
        //    }

        //    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        //    {
        //        return true;
        //    }

        //    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        //    {

        //        return new NothingListItem();
        //    }

        //    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        //    {
        //        return null;
        //    }
        //}

        class ListItemUI : ListBox
        {
            public ListItemUI()
            {
                base.DisplayMember = "Text";
                base.ValueMember = "Item";
                base.BorderStyle = System.Windows.Forms.BorderStyle.None;
                base.ItemHeight = 20;
                base.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
            }

            private bool _acceptNull;

            public bool AcceptNull
            {
                get { return _acceptNull; }
                set { _acceptNull = value; }
            }


            IWindowsFormsEditorService _fesvc;

            public void Start(object value, IListItem[] standardItms, IWindowsFormsEditorService fesvc)
            {
                this.Items.Clear();
                
                NothingListItem nothing;

                if (this.SelectionMode == System.Windows.Forms.SelectionMode.One && AcceptNull)
                {
                    nothing = new NothingListItem();
                    this.Items.Add(nothing);
                }
                else
                    nothing = null;

                this.Items.AddRange(standardItms);

                if (value != null)
                {
                    Array array = value as Array;
                    if (array == null) array = new object[] { value };

                    for (int i = 0; i < Items.Count; i++)
                    {
                        bool selected = false;
                        object sv = ((IListItem)Items[i]).Value;
                        foreach (object cv in array)
                        {
                            object v = cv is IListItem ? ((IListItem)cv).Value : cv;
                            if (object.Equals(sv, v))
                            {
                                selected = true;
                                break;
                            }
                        }
                        if (selected)
                        {
                            this.SetSelected(i, true);
                            if (this.SelectionMode == System.Windows.Forms.SelectionMode.One)
                                break;
                        }
                    }
                }
                else if (nothing != null)
                    base.SetSelected(0, true);
                
                this.Height = Math.Min(Items.Count * ItemHeight, 200);
                _fesvc = fesvc;
            }

            public object Value
            {
                get
                {
                    if (SelectionMode == System.Windows.Forms.SelectionMode.One)
                    {
                        var item = (IListItem)this.SelectedItem;
                        if (item is NothingListItem) return null;
                        else return item;
                    }
                    else
                    {
                        var array = this.SelectedItems.Cast<IListItem>().ToArray();
                        if (array.Length > 0) return array;
                        else return null;
                    }
                }
            }

            protected override void OnClick(EventArgs e)
            {
                if (SelectionMode == System.Windows.Forms.SelectionMode.One)
                {
                    base.OnClick(e);
                    _fesvc.CloseDropDown();
                }
            }

            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                base.OnDrawItem(e);

                if (e.Index != -1)
                {
                    Rectangle rect = e.Bounds;
                    Color foreColor = e.ForeColor;

                    if (SelectionMode == System.Windows.Forms.SelectionMode.One)
                        e.DrawBackground();
                    else
                    {
                        SolidBrush br = new SolidBrush(SystemColors.Window);
                        e.Graphics.FillRectangle(br, rect);
                        br.Dispose();
                        foreColor = SystemColors.WindowText;
                    }

                    IListItem item = (IListItem)this.Items[e.Index];

                    if (SelectionMode != System.Windows.Forms.SelectionMode.One)
                    {
                        System.Windows.Forms.VisualStyles.CheckBoxState state =
                            (e.State & DrawItemState.Selected) == DrawItemState.Selected ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
                        Size size = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
                        size.Width += 2;
                        Rectangle chkrect = new Rectangle(new Point(2, rect.Top + (rect.Height - size.Height) / 2), size);
                        CheckBoxRenderer.DrawCheckBox(e.Graphics, chkrect.Location, state);
                        rect.X += size.Width;
                        rect.Width -= size.Width;
                    }

                    TextRenderer.DrawText(e.Graphics, item.Text, this.Font, rect, foreColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);

                    //e.DrawFocusRectangle();
                }
            }

        }
    }
}
